import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import { ElMessage } from 'element-plus';
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper';
import { useRouter } from 'vue-router';
import TokenManager from './tokenManager';

// 扩展AxiosRequestConfig接口以添加自定义属性
interface CustomAxiosRequestConfig extends AxiosRequestConfig {
  useAuthCenter?: boolean;
  _retry?: boolean;
  requiredRole?: string;
}

// 扩展InternalAxiosRequestConfig接口以添加自定义属性
interface CustomInternalAxiosRequestConfig extends InternalAxiosRequestConfig {
  useAuthCenter?: boolean;
  _retry?: boolean;
  requiredRole?: string;
}

// 创建axios实例
const service: AxiosInstance = axios.create({
  baseURL: '/api', // API基础路径，会被vite代理转发到后端服务器
  timeout: 10000, // 请求超时时间
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  }
});

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const customConfig = config as CustomInternalAxiosRequestConfig;
    
    // 从TokenManager获取token
    const accessToken = TokenManager.getAuthToken();
    
    // 默认使用认证中心的token
    const useAuthCenter = customConfig.useAuthCenter !== false;
    
    // 如果是刷新token的请求，直接通过
    if (config.url?.includes('/auth-center/refresh-token')) {
      return config;
    }
    
    if (useAuthCenter && accessToken) {
      // 检查token是否过期
      if (TokenManager.isTokenExpired()) {
        ElMessage.error('登录已过期，请重新登录');
        // 子应用不负责刷新token，直接返回错误
        return Promise.reject(new Error('登录已过期，请重新登录'));
      } else {
        config.headers.Authorization = `Bearer ${accessToken}`;
        
        if (customConfig.requiredRole) {
          config.headers['X-Required-Role'] = customConfig.requiredRole;
        }
      }
    }
    
    return config;
  },
  error => {
    console.error('请求错误:', error);
    return Promise.reject(error);
  }
);

// 自定义响应类型
interface CustomResponse {
  code?: number;
  message?: string;
  data?: any;
}

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    const config = response.config as CustomAxiosRequestConfig;
    const useAuthCenter = config.useAuthCenter !== false;
    const logPrefix = useAuthCenter ? '[AuthCenter]' : '';
    const customResponse = response.data as CustomResponse;
    if (customResponse && customResponse.hasOwnProperty('code')) {
      if (customResponse.code === 200) {
        return customResponse;
      } else if (customResponse.code === 300 || customResponse.code === 401) {
        console.error(`${logPrefix} 未授权: 代码=${customResponse.code}, 消息=${customResponse.message}`);
        
        if (useAuthCenter) {
          ElMessage.error(`登录已过期，请重新登录`);
        }
        
        return Promise.reject(new Error(customResponse.message || '登录已过期'));
      } else {
        console.error(`${logPrefix} 业务错误: 代码=${customResponse.code}, 消息=${customResponse.message}`);
        ElMessage.error(`${customResponse.message || '请求失败'}`);
        return Promise.reject(new Error(customResponse.message || '请求失败'));
      }
    }
    
    // 没有业务状态码，直接返回数据
    return response.data;
  },
  async error => {
    // 获取原始请求配置
    const originalRequest = error.config as CustomAxiosRequestConfig;
    const useAuthCenter = originalRequest?.useAuthCenter !== false;
    const logPrefix = useAuthCenter ? '[AuthCenter]' : '';
    
    // 如果是401错误（未授权）且使用认证中心token
    if (error.response?.status === 401 && useAuthCenter) {
      // 子应用不负责刷新token，直接提示用户
      ElMessage.error('登录已过期，请重新登录');
      console.error(`${logPrefix} 登录已过期，请在基座应用中重新登录`);
    }
    
    // 处理响应错误
    console.error(`${logPrefix} 响应错误:`, error);
    
    // 获取错误状态码
    const status = error.response ? error.response.status : null;
    
    // 详细记录错误信息
    if (error.response) {
      console.error(`${logPrefix} 错误响应: ${error.config?.method?.toUpperCase()} ${error.config?.url}`);
      console.error(`${logPrefix} 状态码: ${status}`);
      console.error(`${logPrefix} 响应头:`, JSON.stringify(error.response.headers, null, 2));
      console.error(`${logPrefix} 错误数据:`, JSON.stringify(error.response.data, null, 2));
    }
    
    // 根据状态码处理不同情况
    if (status === 401) {
      if (useAuthCenter) {
        ElMessage.error(`${logPrefix} 登录已过期，请重新登录`);
      }
    } else if (status === 403) {
      // 权限不足
      ElMessage.error(`${logPrefix} 权限不足，无法访问`);
    } else if (status === 404) {
      // 资源不存在
      ElMessage.error(`${logPrefix} 请求的资源不存在`);
    } else if (status === 500) {
      // 服务器错误
      const errorMessage = error.response?.data?.message || '服务器错误';
      const errorType = error.response?.data?.error || '';
      ElMessage.error(`${logPrefix} 服务器错误${errorType ? `(${errorType})` : ''}: ${errorMessage}`);
    } else if (status === 400) {
      // 请求错误
      let errorMessage = '请求参数错误';
      if (error.response?.data?.message) {
        const message = error.response.data.message;
        if (Array.isArray(message) && message.length > 0) {
          errorMessage = message[0]; // 显示第一个错误消息
        } else {
          errorMessage = message;
        }
      }
      ElMessage.error(`${logPrefix} ${errorMessage}`);
    } else {
      // 其他错误
      ElMessage.error(`${logPrefix} ${error.response?.data?.message || '请求失败，请稍后再试'}`);
    }
    
    return Promise.reject(error);
  }
);

// HTTP请求方法
interface Http {
  get: (url: string, params?: any, isAdmin?: boolean, useAuthCenter?: boolean, requiredRole?: string) => Promise<any>;
  post: (url: string, data?: any, isAdmin?: boolean, json?: boolean, useAuthCenter?: boolean, requiredRole?: string) => Promise<any>;
  put: (url: string, data?: any, isAdmin?: boolean, useAuthCenter?: boolean, requiredRole?: string) => Promise<any>;
  patch: (url: string, data?: any, isAdmin?: boolean, useAuthCenter?: boolean, requiredRole?: string) => Promise<any>;
  delete: (url: string, params?: any, isAdmin?: boolean, useAuthCenter?: boolean, requiredRole?: string, useBody?: boolean) => Promise<any>;
}

const http: Http = {
  /**
   * GET请求
   * @param {string} url - 请求地址
   * @param {object} params - 请求参数
   * @param {boolean} isAdmin - 是否是管理员请求
   * @param {boolean} useAuthCenter - 是否使用认证中心token
   * @param {string} requiredRole - 所需角色
   * @returns {Promise} - 返回Promise
   */
  get(url, params = {}, isAdmin = false, useAuthCenter = true, requiredRole = '') {
    return service.get(url, {
      params,
      useAuthCenter,
      requiredRole
    } as CustomAxiosRequestConfig);
  },

  /**
   * POST请求
   * @param {string} url - 请求地址
   * @param {object} data - 请求数据
   * @param {boolean} isAdmin - 是否是管理员请求
   * @param {boolean} json - 是否以JSON格式发送
   * @param {boolean} useAuthCenter - 是否使用认证中心token
   * @param {string} requiredRole - 所需角色
   * @returns {Promise} - 返回Promise
   */
  post(url, data = {}, isAdmin = false, json = true, useAuthCenter = true, requiredRole = '') {
    return service.post(url, data, {
      useAuthCenter,
      requiredRole
    } as CustomAxiosRequestConfig);
  },

  /**
   * PUT请求
   * @param {string} url - 请求地址
   * @param {object} data - 请求数据
   * @param {boolean} isAdmin - 是否是管理员请求
   * @param {boolean} useAuthCenter - 是否使用认证中心token
   * @param {string} requiredRole - 所需角色
   * @returns {Promise} - 返回Promise
   */
  put(url, data = {}, isAdmin = false, useAuthCenter = true, requiredRole = '') {
    return service.put(url, data, {
      useAuthCenter,
      requiredRole
    } as CustomAxiosRequestConfig);
  },

  /**
   * PATCH请求
   * @param {string} url - 请求地址
   * @param {object} data - 请求数据
   * @param {boolean} isAdmin - 是否是管理员请求
   * @param {boolean} useAuthCenter - 是否使用认证中心token
   * @param {string} requiredRole - 所需角色
   * @returns {Promise} - 返回Promise
   */
  patch(url, data = {}, isAdmin = false, useAuthCenter = true, requiredRole = '') {
    return service.patch(url, data, {
      useAuthCenter,
      requiredRole
    } as CustomAxiosRequestConfig);
  },

  /**
   * DELETE请求
   * @param {string} url - 请求地址
   * @param {object} params - 请求参数（可以是查询参数或body数据）
   * @param {boolean} isAdmin - 是否是管理员请求
   * @param {boolean} useAuthCenter - 是否使用认证中心token
   * @param {string} requiredRole - 所需角色
   * @param {boolean} useBody - 是否使用body传递数据（默认false，使用查询参数）
   * @returns {Promise} - 返回Promise
   */
  delete(url, params = {}, isAdmin = false, useAuthCenter = true, requiredRole = '', useBody = false) {
    const config: CustomAxiosRequestConfig = {
      useAuthCenter,
      requiredRole
    };
    
    if (useBody) {
      // 使用 body 传递数据
      config.data = params;
    } else {
      // 使用查询参数
      config.params = params;
    }
    
    return service.delete(url, config);
  }
};

export default http; 